package com.ycl.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Description 压缩与解压工具
 * @Author yanghanwei
 * @Date 18:42 2019-11-20
 * @Version v1
 **/
public class ZipUtils {

    private static final Logger logger = LoggerFactory.getLogger(ZipUtils.class);

    /**
     * 压缩 zip
     *
     * @param outPath 压缩文件保存路径
     * @param list
     */
    public static void zipFile(String outPath, Map<String, BufferedImage> list, String imgType) {
        try {
            //创建Test.zip文件
            OutputStream is = new FileOutputStream(outPath);
            //检查输出流,采用CRC32算法，保证文件的一致性
            CheckedOutputStream cos = new CheckedOutputStream(is, new CRC32());
            //创建zip文件的输出流
            ZipOutputStream zos = new ZipOutputStream(cos);
            //压缩文件的具体实现函数
            zipFilePost(zos, list, imgType);
            zos.close();
            cos.close();
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 压缩文件
     *
     * @param zos zip文件的输出流
     * @param map
     */
    private static void zipFilePost(ZipOutputStream zos, Map<String, BufferedImage> map, String imgType) {

        try {
            // 创建压缩文件
            for (Map.Entry<String, BufferedImage> entry : map.entrySet()) {
                String key = entry.getKey();
                zos.putNextEntry(new ZipEntry(key + "." + imgType));
                BufferedImage is = entry.getValue();
                try{
                    byte[] b1 = toJpg(is, imgType);
                    zos.write(b1);
                }catch (UnsupportedOperationException unsupportedOperationException){
                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                    ImageIO.write(is, imgType, os);
                    InputStream input = new ByteArrayInputStream(os.toByteArray());
                    // 创建一个缓存区
                    BufferedInputStream bis = new BufferedInputStream(input);
                    // 字节数组,每次读取1024个字节
                    byte[] b = new byte[1024];
                    // 循环读取，边读边写
                    while (bis.read(b) != -1) {
                        // 写入压缩文件
                        zos.write(b);
                    }
                    bis.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static byte[] toJpg(BufferedImage image, String imgType) throws IOException {
        // Manually get the ImageWriter to be able to adjust quality
        ImageWriter writer = ImageIO.getImageWritersBySuffix(imgType).next();
        ImageWriteParam imageWriterParam = writer.getDefaultWriteParam();
        imageWriterParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        imageWriterParam.setCompressionQuality(1);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        writer.setOutput(new MemoryCacheImageOutputStream(output));
        writer.write(null, new IIOImage(image, null, null), imageWriterParam);
        writer.dispose();
        return output.toByteArray();
    }
}